#include "ssiot/ssiot.h"
#include <stdio.h>
#include <time.h>
#include <chrono>
#include <thread>
#include "ssiot/msgbus.h"
#include "ssiot/settings.h"

SSIoT* SSIoT::ssiot = NULL;

SSIoT::SSIoT()
{
	msgbus_ = NULL;
}

SSIoT::~SSIoT()
{

}

SSIoT* SSIoT::INST(void)
{
	if (SSIoT::ssiot == NULL) {
		SSIoT::ssiot = new SSIoT();
	}
	return SSIoT::ssiot;
}

int SSIoT::Init(int argc, char** argv)
{
	settings_ = new Settings();
	settings_->LoadFromFile("./config/settings.json");

	nlohmann::json cfg;
	char sn[128];
	sprintf(sn, "LAI%ld", time(NULL));

	for (int i = 0; i < argc; i++) {
		if (strcmp("-sn", argv[i]) == 0) {
			memset(sn, 0, 128);
			strcpy(sn, argv[i]);
		}
	}

	cfg["sn"] = sn;
	cfg["model"] = "ssiot-applet-liteai";
	cfg["auth"] = "";
	cfg["mqtt"] = {
		{"address", "172.16.22.132:9010"}, 
		{"username", "ssiot"},
		{"password", "!@#abcd"}
	};

	settings_->LoadSettings("ssiot", cfg);

	fprintf(stderr, "\n%s\n", cfg.dump().c_str());

	msgbus_ = new Msgbus(cfg["sn"]);

	for (int i = 0; i < 1000; i++ ) {
		if (msgbus_->Connect(cfg["mqtt"]["address"], cfg["mqtt"]["username"], cfg["mqtt"]["password"]) != 0) {
			fprintf(stderr, "connect to mqtt error. %s", cfg["mqtt"].dump().c_str());
			return -1;
		}

		nlohmann::json login;
		login["model"] = cfg["model"];

		IoTMsg msg(SSIOT_LOGIN, "", "", login);
		IoTMsg ack = SSIoT::INST()->msgbug()->SyncPublish(msg);
		if (ack.code != 200) {
			fprintf(stderr, "login error. %d", ack.code);
			std::this_thread::sleep_for(std::chrono::seconds(i));
			continue;
		}

		std::string go = ack.data["goto"];
		if(go.length() > 0){
			cfg["mqtt"]["address"] = go;
			cfg["mqtt"]["username"] = ack.data["username"];
			cfg["mqtt"]["password"] = ack.data["password"];
			msgbus_->Disconn();
			fprintf(stdout, "login goto %s", cfg["mqtt"].dump().c_str());
			continue;
		}

		fprintf(stdout, "login success \n");
		break;
	}

	settings_->SyncSettings("ssiot", cfg);

	return 0;
}

void SSIoT::Fini()
{
	SSIoT::INST()->msgbug()->SyncPublish(IoTMsg(SSIOT_LOGOUT, "", "", ""));
}

std::string  SSIoT::SN(void) 
{
	return settings_->getSettings("ssiot")["sn"];
}

std::string SSIoT::Service(void)
{
	std::string address = settings_->getSettings("ssiot")["mqtt"]["address"];

	int pos = address.find(":");
	if (pos < address.length()) {
		std::string addr = address.substr(0, pos);
		return addr;
	}
	return address;
}